// PGLObjectPool.h: interface for the CPGLObjectPool class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_PGLOBJECTPOOL_H__94EF7A3C_66B5_470A_9DFF_CC93DCBC5DCA__INCLUDED_)
#define AFX_PGLOBJECTPOOL_H__94EF7A3C_66B5_470A_9DFF_CC93DCBC5DCA__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#pragma warning(disable: 4786)  // identifier was truncated to 'number' characters in the debug information



namespace pgl
{
	namespace priv
	{
		template<typename TNew, class M>
		class SecondIsClassSum : 
			public std::binary_function<
				typename M::size_type, 
				typename M::size_type, 
				typename M::value_type
		>
		{
		public:
			typename M::size_type operator() (
				typename M::size_type sumSoFar, 
				typename M::value_type vt)
			{
				if ( boost::static_dynamic_cast<TNew, M::referent_type::value_type>( vt.second) )
					return ++sumSoFar;
				else 
					return sumSoFar;
			}
		};


	}
}

class CPGLNodePoolSingleton;
class CPGLNodePool  
{
public:
	CPGLNodePool();
	virtual ~CPGLNodePool();

	typedef CPGLNodeStPtr Node;
	typedef CPGLNode NodeValue;
	typedef std::map<long, CPGLNodeStPtr> NodeContainer;

private:
	friend CPGLNodePoolSingleton;
	friend NodeValue;

	//! insert pointer in Pool and returns the corresponding ID
	long InsertNode(Node pNode);
	//! insert pointer in Pool and return if succeded
	void InsertNodeFixedID(Node pNode);
	//! erase object from map	
	bool RemoveNode(long lID);
	//! changes the ID of an object
	bool ChangeID( Node pNode, long uNewID);

	template <typename T>
	size_t GetTypedCount(boost::static_ptr<T> p)
	{
		// call the function to create it
		return std::accumulate( 
				m_mNodes.begin(), 
				m_mNodes.end(), 
				0, 
				pgl::priv::SecondIsClassSum<T, NodeContainer>() 
				);
	}

	//! return object count
	size_t GetCount() const		{	return m_mNodes.size();};

	//! return pointer to object with ID = uID
	Node FindNode(long uID);

#ifdef _DEBUG
	void Dump();
#endif
private:
	NodeContainer m_mNodes;
	long m_uCurrentID;
	CMutex m_mutex;

};


/*!
  \defgroup PGLCoreSingletonGroup Singletons
  \ingroup PGLCoreGroup
*/

/*! \brief Map between object ID and object address.


  \ingroup PGLCoreSingletonGroup
*/
class PGLCORE_EXT_CLASS CPGLNodePoolSingleton : public singletons::TSingleton<CPGLNodePool, 4>
{
public:
	typedef CPGLNodePool::Node Node;
	typedef CPGLNodePool::NodeValue NodeValue;
	typedef CPGLNodePool::NodeContainer NodeContainer;

	//! \name Accessible methods
	//@{
	//! Returns the number of active objects
	static size_t GetCount();
	static size_t GetObjectCount();
	static size_t GetDataCount();
	static size_t GetBrushCount();

	//! find object by ID
	static Node FindNode(long uID);
	//@}

#ifdef _DEBUG
	static void Dump();
#endif
};



#endif // !defined(AFX_PGLOBJECTPOOL_H__94EF7A3C_66B5_470A_9DFF_CC93DCBC5DCA__INCLUDED_)
